//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension NotificationsContacts {
    // MARK: Enums

    public enum EmailContactStatus: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "active"
        case inactive = "inactive"
        public var description: String { return self.rawValue }
    }

    public enum ValidationExceptionReason: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case fieldValidationFailed = "fieldValidationFailed"
        case other = "other"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct ActivateEmailContactRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource.
        public let arn: String
        /// The activation code for this email contact. An email contact has a maximum of five activation attempts. Activation codes expire after 12 hours and are generated by the SendActivationCode API action.
        public let code: String

        @inlinable
        public init(arn: String, code: String) {
            self.arn = arn
            self.code = code
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.arn, key: "arn")
            request.encodePath(self.code, key: "code")
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:notifications-contacts::[0-9]{12}:emailcontact/[a-z0-9]{27}$")
            try self.validate(self.code, name: "code", parent: name, max: 7)
            try self.validate(self.code, name: "code", parent: name, min: 7)
            try self.validate(self.code, name: "code", parent: name, pattern: "^[a-z0-9]{7}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ActivateEmailContactResponse: AWSDecodableShape {
        public init() {}
    }

    public struct ConflictException: AWSErrorShape {
        public let message: String
        /// The resource ID that prompted the conflict error.
        public let resourceId: String
        /// The resource type that prompted the conflict error.
        public let resourceType: String

        @inlinable
        public init(message: String, resourceId: String, resourceType: String) {
            self.message = message
            self.resourceId = resourceId
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case resourceId = "resourceId"
            case resourceType = "resourceType"
        }
    }

    public struct CreateEmailContactRequest: AWSEncodableShape {
        /// The email address this email contact points to. The activation email and any subscribed emails are sent here.  This email address can't receive emails until it's activated.
        public let emailAddress: String
        /// The name of the email contact.
        public let name: String
        /// A map of tags assigned to a resource. A tag is a string-to-string map of key-value pairs.
        public let tags: [String: String]?

        @inlinable
        public init(emailAddress: String, name: String, tags: [String: String]? = nil) {
            self.emailAddress = emailAddress
            self.name = name
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, max: 254)
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, min: 6)
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, pattern: "^(.+)@(.+)$")
            try self.validate(self.name, name: "name", parent: name, max: 64)
            try self.validate(self.name, name: "name", parent: name, min: 1)
            try self.validate(self.name, name: "name", parent: name, pattern: "[\\w-.~]+")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:).{1,128}$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case emailAddress = "emailAddress"
            case name = "name"
            case tags = "tags"
        }
    }

    public struct CreateEmailContactResponse: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the resource.
        public let arn: String

        @inlinable
        public init(arn: String) {
            self.arn = arn
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
        }
    }

    public struct DeleteEmailContactRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource.
        public let arn: String

        @inlinable
        public init(arn: String) {
            self.arn = arn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.arn, key: "arn")
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:notifications-contacts::[0-9]{12}:emailcontact/[a-z0-9]{27}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteEmailContactResponse: AWSDecodableShape {
        public init() {}
    }

    public struct EmailContact: AWSDecodableShape {
        /// The email address this email contact points to. The activation email and any subscribed emails are sent here.
        public let address: String
        /// The Amazon Resource Name (ARN) of the email contact.
        public let arn: String
        /// The creation time of the resource.
        @CustomCoding<ISO8601DateCoder>
        public var creationTime: Date
        /// The name of the email contact.
        public let name: String
        /// The status of the email contact. Only activated email contacts receive emails.
        public let status: EmailContactStatus
        /// The time the resource was last updated.
        @CustomCoding<ISO8601DateCoder>
        public var updateTime: Date

        @inlinable
        public init(address: String, arn: String, creationTime: Date, name: String, status: EmailContactStatus, updateTime: Date) {
            self.address = address
            self.arn = arn
            self.creationTime = creationTime
            self.name = name
            self.status = status
            self.updateTime = updateTime
        }

        private enum CodingKeys: String, CodingKey {
            case address = "address"
            case arn = "arn"
            case creationTime = "creationTime"
            case name = "name"
            case status = "status"
            case updateTime = "updateTime"
        }
    }

    public struct GetEmailContactRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the email contact to get.
        public let arn: String

        @inlinable
        public init(arn: String) {
            self.arn = arn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.arn, key: "arn")
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:notifications-contacts::[0-9]{12}:emailcontact/[a-z0-9]{27}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetEmailContactResponse: AWSDecodableShape {
        /// The email contact for the provided email address.
        public let emailContact: EmailContact

        @inlinable
        public init(emailContact: EmailContact) {
            self.emailContact = emailContact
        }

        private enum CodingKeys: String, CodingKey {
            case emailContact = "emailContact"
        }
    }

    public struct ListEmailContactsRequest: AWSEncodableShape {
        /// The maximum number of results to include in the response. If more results exist than the specified MaxResults value, a token is included in the response so that the remaining results can be retrieved.
        public let maxResults: Int?
        /// An optional token returned from a prior request. Use this token for pagination of results from this action. If this parameter is specified, the response includes only results beyond the token, up to the value specified by MaxResults.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.maxResults, key: "maxResults")
            request.encodeQuery(self.nextToken, key: "nextToken")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListEmailContactsResponse: AWSDecodableShape {
        /// A list of email contacts.
        public let emailContacts: [EmailContact]
        /// An optional token returned from a prior request. Use this token for pagination of results from this action. If this parameter is specified, the response includes only results beyond the token, up to the value specified by MaxResults.
        public let nextToken: String?

        @inlinable
        public init(emailContacts: [EmailContact], nextToken: String? = nil) {
            self.emailContacts = emailContacts
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case emailContacts = "emailContacts"
            case nextToken = "nextToken"
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        /// The ARN you specified to list the tags of.
        public let arn: String

        @inlinable
        public init(arn: String) {
            self.arn = arn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.arn, key: "arn")
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:notifications-contacts::[0-9]{12}:emailcontact/[a-z0-9]{27}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// Key-value pairs that are assigned to a resource, usually for the purpose of grouping and searching for items. Tags are metadata that you define.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct ResourceNotFoundException: AWSErrorShape {
        public let message: String
        /// The ID of the resource that wasn't found.
        public let resourceId: String
        /// The type of resource that wasn't found.
        public let resourceType: String

        @inlinable
        public init(message: String, resourceId: String, resourceType: String) {
            self.message = message
            self.resourceId = resourceId
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case resourceId = "resourceId"
            case resourceType = "resourceType"
        }
    }

    public struct SendActivationCodeRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource.
        public let arn: String

        @inlinable
        public init(arn: String) {
            self.arn = arn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.arn, key: "arn")
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:notifications-contacts::[0-9]{12}:emailcontact/[a-z0-9]{27}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct SendActivationCodeResponse: AWSDecodableShape {
        public init() {}
    }

    public struct ServiceQuotaExceededException: AWSErrorShape {
        public let message: String
        /// The code for the service quota in Service Quotas.
        public let quotaCode: String
        /// The ID of the resource that exceeds the service quota.
        public let resourceId: String
        /// The type of the resource that exceeds the service quota.
        public let resourceType: String
        /// The code for the service quota exceeded in Service Quotas.
        public let serviceCode: String

        @inlinable
        public init(message: String, quotaCode: String, resourceId: String, resourceType: String, serviceCode: String) {
            self.message = message
            self.quotaCode = quotaCode
            self.resourceId = resourceId
            self.resourceType = resourceType
            self.serviceCode = serviceCode
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case quotaCode = "quotaCode"
            case resourceId = "resourceId"
            case resourceType = "resourceType"
            case serviceCode = "serviceCode"
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        /// The ARN of the configuration.
        public let arn: String
        /// A list of tags to apply to the configuration.
        public let tags: [String: String]

        @inlinable
        public init(arn: String, tags: [String: String]) {
            self.arn = arn
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.arn, key: "arn")
            try container.encode(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:notifications-contacts::[0-9]{12}:emailcontact/[a-z0-9]{27}$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:).{1,128}$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct ThrottlingException: AWSErrorShape {
        public let message: String
        /// Identifies the quota that is being throttled.
        public let quotaCode: String?
        /// The number of seconds a client should wait before retrying the request.
        public let retryAfterSeconds: Int?
        /// Identifies the service being throttled.
        public let serviceCode: String?

        @inlinable
        public init(message: String, quotaCode: String? = nil, retryAfterSeconds: Int? = nil, serviceCode: String? = nil) {
            self.message = message
            self.quotaCode = quotaCode
            self.retryAfterSeconds = retryAfterSeconds
            self.serviceCode = serviceCode
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.message = try container.decode(String.self, forKey: .message)
            self.quotaCode = try container.decodeIfPresent(String.self, forKey: .quotaCode)
            self.retryAfterSeconds = try response.decodeHeaderIfPresent(Int.self, key: "Retry-After")
            self.serviceCode = try container.decodeIfPresent(String.self, forKey: .serviceCode)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case quotaCode = "quotaCode"
            case serviceCode = "serviceCode"
        }
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        /// The value of the resource that will have the tag removed. An Amazon Resource Name (ARN) is an identifier for a specific AWS resource, such as a server, user, or role.
        public let arn: String
        /// Specifies a list of tag keys that you want to remove from the specified resources.
        public let tagKeys: [String]

        @inlinable
        public init(arn: String, tagKeys: [String]) {
            self.arn = arn
            self.tagKeys = tagKeys
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.arn, key: "arn")
            request.encodeQuery(self.tagKeys, key: "tagKeys")
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "^arn:aws:notifications-contacts::[0-9]{12}:emailcontact/[a-z0-9]{27}$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^(?!aws:).{1,128}$")
            }
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct ValidationException: AWSErrorShape {
        /// The list of input fields that are invalid.
        public let fieldList: [ValidationExceptionField]?
        public let message: String
        /// The reason why your input is considered invalid.
        public let reason: ValidationExceptionReason

        @inlinable
        public init(fieldList: [ValidationExceptionField]? = nil, message: String, reason: ValidationExceptionReason) {
            self.fieldList = fieldList
            self.message = message
            self.reason = reason
        }

        private enum CodingKeys: String, CodingKey {
            case fieldList = "fieldList"
            case message = "message"
            case reason = "reason"
        }
    }

    public struct ValidationExceptionField: AWSDecodableShape {
        /// A message with the reason for the validation exception error.
        public let message: String
        /// The field name where the invalid entry was detected.
        public let name: String

        @inlinable
        public init(message: String, name: String) {
            self.message = message
            self.name = name
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case name = "name"
        }
    }
}

// MARK: - Errors

/// Error enum for NotificationsContacts
public struct NotificationsContactsErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize NotificationsContacts
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// You do not have sufficient access to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// Updating or deleting a resource can cause an inconsistent state.
    public static var conflictException: Self { .init(.conflictException) }
    /// Unexpected error during processing of request.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// Your request references a resource which does not exist.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    ///  Request would cause a service quota to be exceeded.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The request was denied due to request throttling.
    public static var throttlingException: Self { .init(.throttlingException) }
    /// The input fails to satisfy the constraints specified by an AWS service.
    public static var validationException: Self { .init(.validationException) }
}

extension NotificationsContactsErrorType: AWSServiceErrorType {
    public static let errorCodeMap: [String: AWSErrorShape.Type] = [
        "ConflictException": NotificationsContacts.ConflictException.self,
        "ResourceNotFoundException": NotificationsContacts.ResourceNotFoundException.self,
        "ServiceQuotaExceededException": NotificationsContacts.ServiceQuotaExceededException.self,
        "ThrottlingException": NotificationsContacts.ThrottlingException.self,
        "ValidationException": NotificationsContacts.ValidationException.self
    ]
}

extension NotificationsContactsErrorType: Equatable {
    public static func == (lhs: NotificationsContactsErrorType, rhs: NotificationsContactsErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension NotificationsContactsErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
